package com.bigdata.assignment.problem1;

import java.io.IOException;
import java.text.Normalizer;
import java.util.regex.Pattern;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

/**
 * WordCountMapper
 * --------------
 * 功能：读取输入文本的每一行，进行分词并输出 (单词, 1) 键值对。
 *
 * 改进点：
 * 1. 使用 Unicode 正则，支持非拉丁文字（\\p{L} = Unicode 字母, \\p{N} = Unicode 数字）
 * 2. 对带重音字符（例如 café）做 Unicode 规范化并去掉变音符号 -> "cafe"
 * 3. 过滤空字符串并 trim
 * 4. 所有词统一为小写
 */
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {

    private final static IntWritable one = new IntWritable(1);
    private final Text word = new Text();

    // 分隔正则：以非字母且非数字字符为分隔符（支持 Unicode）
    private static final Pattern SPLIT_PATTERN = Pattern.compile("[^\\p{L}\\p{N}]+");

    @Override
    protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {

        if (value == null) {
            return;
        }

        // 1) 获取当前行文本并转换为小写（统一大小写）
        String line = value.toString().toLowerCase();

        // 2) Unicode 规范化：将组合字符分解，再去掉变音符号（例如 'é' -> 'e'）
        //    这样可以将带变音的字符规范化为基础字母，便于统计
        String normalized = Normalizer.normalize(line, Normalizer.Form.NFD)
                                      .replaceAll("\\p{M}", ""); // 去掉所有变音符号（Mark）

        // 3) 按照正则分割（以非字母/非数字为分隔符）
        String[] tokens = SPLIT_PATTERN.split(normalized);

        // 4) 遍历词元并输出 (word, 1)
        for (String token : tokens) {
            if (token == null) continue;
            token = token.trim();
            if (token.isEmpty()) continue;

            // 额外过滤（可选）：如果需要过滤掉纯数字的 token，可在此处加入判断
            // if (token.matches("^\\d+$")) continue;

            word.set(token);
            context.write(word, one);
        }
    }
}

